using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using TabControlLib.Tools;

namespace TabControlLib.Controls
{
    [TemplatePart(Name = ElementSliding, Type = typeof(FrameworkElement))]
    public class SlidingTabContainer : ContentControl
    {
        private const string ElementSliding = "PART_Sliding";

        private FrameworkElement _sliding = new();
        private System.Windows.Controls.TabControl _tabControl;

        public SlidingTabContainer()
        {
            Loaded += OnLoaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Loaded -= OnLoaded;
            OnSelectionChanged(null, null);
        }

        public override void OnApplyTemplate()
        {
            if (_tabControl is not null)
            {
                _tabControl.SelectionChanged -= OnSelectionChanged;
            }

            base.OnApplyTemplate();

            _tabControl = VisualHelper.GetParent<System.Windows.Controls.TabControl>(this);
            _sliding = GetTemplateChild(ElementSliding) as FrameworkElement;

            if (_tabControl is not null)
            {
                _tabControl.SelectionChanged += OnSelectionChanged;

                if (IsLoaded)
                {
                    OnSelectionChanged(null, null);
                }
            }
        }

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);

            if (_tabControl is null)
            {
                return;
            }

            OnSelectionChanged(null, null);
        }

        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (_sliding is null || !IsLoaded)
            {
                return;
            }

            if (_tabControl.ItemContainerGenerator.ContainerFromItem(_tabControl.SelectedItem) is not System.Windows.Controls.TabItem tabItem)
            {
                return;
            }

            var offset = VisualHelper.GetOffset(tabItem);
            var tabWidth = tabItem.ActualWidth;
            var tabHeight = tabItem.ActualHeight;
            var useAnimation = _sliding.Width > 0 && _sliding.Height > 0;

            if (useAnimation)
            {
                var storyboard = new Storyboard();
                var easingFuction = new PowerEase
                {
                    EasingMode = EasingMode.EaseOut,
                };

                var widthAnimation = AnimationHelper.CreateAnimation(tabWidth);
                widthAnimation.EasingFunction = easingFuction;
                Storyboard.SetTarget(widthAnimation, _sliding);
                Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(WidthProperty.Name));
                storyboard.Children.Add(widthAnimation);

                var heightAnimation = AnimationHelper.CreateAnimation(tabHeight);
                heightAnimation.EasingFunction = easingFuction;
                Storyboard.SetTarget(heightAnimation, _sliding);
                Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(HeightProperty.Name));
                storyboard.Children.Add(heightAnimation);

                var xAnimation = AnimationHelper.CreateAnimation(offset.X);
                xAnimation.EasingFunction = easingFuction;
                Storyboard.SetTarget(xAnimation, _sliding);
                Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
                storyboard.Children.Add(xAnimation);

                var yAnimation = AnimationHelper.CreateAnimation(offset.Y);
                yAnimation.EasingFunction = easingFuction;
                Storyboard.SetTarget(yAnimation, _sliding);
                Storyboard.SetTargetProperty(yAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));
                storyboard.Children.Add(yAnimation);

                storyboard.Begin();
            }
            else
            {
                _sliding.Width = tabItem.ActualWidth;
                _sliding.Height = tabItem.ActualHeight;
                _sliding.RenderTransform = new TranslateTransform(offset.X, offset.Y);
            }
        }
    }
}
